Sources/XCMetricsClient/Mobius/Effect Handlers/DumpParser/DumpReader.swift (34 lines of code) (raw):

// Copyright (c) 2020 Spotify AB. // // Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. import Foundation /// Single line file stream reader private class LineStreamReader { private let encoding = String.Encoding.utf8 private let chunkSize = 4096 private let fileHandle: FileHandle private var buffer: Data private let delimiter = "\n".data(using: .utf8)! private var isEOF = false init(url: URL) throws { let fileHandle = try FileHandle(forReadingFrom: url) self.fileHandle = fileHandle buffer = Data(capacity: chunkSize) } deinit { fileHandle.closeFile() } func nextLine() -> Data? { if isEOF { return nil } repeat { if let range = buffer.range(of: delimiter, options: [], in: buffer.startIndex..<buffer.endIndex) { let bufferSliceData = buffer.subdata(in: buffer.startIndex..<range.lowerBound) buffer.replaceSubrange(buffer.startIndex..<range.upperBound, with: []) return bufferSliceData } else { let tempData = fileHandle.readData(ofLength: chunkSize) if tempData.count == 0 { isEOF = true // left state of a buffer return (buffer.count > 0) ? buffer : nil } buffer.append(tempData) } } while true } }